"""Starlark bazel build configurations, see https://bazel.build/extending/config"""

# =============
# compiler_type
# =============

compiler_type_values = ["gcc", "clang", "msvc"]

compiler_type_provider = provider(
    doc = "Select the compiler (e.g.: gcc)",
    fields = {"compiler_type": "Choose one of " + ".".join(compiler_type_values)},
)

def compiler_type_impl(ctx):
    compiler_type_value = ctx.build_setting_value
    if compiler_type_value not in compiler_type_values:
        fail(str(ctx.label) + " compiler_type allowed to take values {" + ", ".join(compiler_type_values) + "} but was set to unallowed value " + compiler_type_value)

    return compiler_type_provider(compiler_type = compiler_type_value)

compiler_type = rule(
    implementation = compiler_type_impl,
    build_setting = config.string(flag = True),
)

# =========
# mongo_toolchain_version
# =========

mongo_toolchain_version_values = ["v5"]

mongo_toolchain_version_provider = provider(
    doc = "Select the mongo toolchain version (e.g.: v5)",
    fields = {"mongo_toolchain_version": "Choose one of " + ".".join(mongo_toolchain_version_values)},
)

def mongo_toolchain_version_impl(ctx):
    mongo_toolchain_version_value = ctx.build_setting_value
    if mongo_toolchain_version_value not in mongo_toolchain_version_values:
        fail(str(ctx.label) + " mongo_toolchain_version allowed to take values {" + ", ".join(mongo_toolchain_version_values) + "} but was set to unallowed value " + mongo_toolchain_version_value)
    return mongo_toolchain_version_provider(mongo_toolchain_version = mongo_toolchain_version_value)

mongo_toolchain_version = rule(
    implementation = mongo_toolchain_version_impl,
    build_setting = config.string(flag = True),
)

# ==========
# linker
# ==========

linker_values = ["auto", "gold", "lld", "mold"]

linker_provider = provider(
    doc = "Specify the type of linker to use.",
    fields = {"linker": "choose one of " + ".".join(linker_values)},
)

def linker_impl(ctx):
    linker_value = ctx.build_setting_value
    if linker_value not in linker_values:
        fail(str(ctx.label) + " linker allowed to take values {" + ", ".join(linker_values) + "} but was set to unallowed value " + linker_value)
    return linker_provider(linker = linker_value)

linker = rule(
    implementation = linker_impl,
    build_setting = config.string(flag = True),
)

# =========
# gdbserver
# =========

use_gdbserver_provider = provider(
    doc = "Choose if gdbserver should be used",
    fields = ["enabled"],
)

use_gdbserver = rule(
    implementation = lambda ctx: use_gdbserver_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# libunwind
# =========

libunwind_values = ["auto", "on", "off"]

libunwind_provider = provider(
    doc = "Enable libunwind for backtraces (use \"auto\" to enable only if its available on the current platform)",
    fields = {"libunwind": "choose one of " + ".".join(libunwind_values)},
)

def libunwind_impl(ctx):
    libunwind_value = ctx.build_setting_value
    if libunwind_value not in libunwind_values:
        fail(str(ctx.label) + " libunwind allowed to take values {" + ", ".join(libunwind_values) + "} but was set to unallowed value " + libunwind_value)
    return libunwind_provider(libunwind = libunwind_value)

libunwind = rule(
    implementation = libunwind_impl,
    build_setting = config.string(flag = True),
)

# =========
# spider_monkey_dbg
# =========

spider_monkey_dbg_provider = provider(doc = "Enable SpiderMonkey debug mode.", fields = ["enabled"])

spider_monkey_dbg = rule(
    implementation = lambda ctx: spider_monkey_dbg_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# include_mongot
# =========

include_mongot_provider = provider(doc = "Enable including mongot in the final binary archive from a local mongot-localdev folder.", fields = ["enabled"])

include_mongot = rule(
    implementation = lambda ctx: include_mongot_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# include_autogenerated_targets
# =========

include_autogenerated_targets_provider = provider(doc = "Enable using autogenerated build targets.", fields = ["enabled"])

include_autogenerated_targets = rule(
    implementation = lambda ctx: include_autogenerated_targets_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# allocator
# =========

allocator_values = ["auto", "system", "tcmalloc-gperf", "tcmalloc-google"]

allocator_provider = provider(
    doc = "Allocator to use (use \"auto\" for best choice for current platform)",
    fields = {"allocator": "choose one of " + ".".join(allocator_values)},
)

def allocator_impl(ctx):
    allocator_value = ctx.build_setting_value
    if allocator_value not in allocator_values:
        fail(str(ctx.label) + " allocator allowed to take values {" + ", ".join(allocator_values) + "} but was set to unallowed value " + allocator_value)
    return allocator_provider(allocator = allocator_value)

allocator = rule(
    implementation = allocator_impl,
    build_setting = config.string(flag = True),
)

# =========
# lldb-server
# =========

use_lldbserver_provider = provider(
    doc = "Choose if lldbserver should be used",
    fields = ["enabled"],
)

use_lldbserver = rule(
    implementation = lambda ctx: use_lldbserver_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# wait_for_debugger
# =========

use_wait_for_debugger_provider = provider(
    doc = "Wait for debugger attach on process startup",
    fields = ["enabled"],
)

use_wait_for_debugger = rule(
    implementation = lambda ctx: use_wait_for_debugger_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# ocsp-stapling
# =========

use_ocsp_stapling_provider = provider(
    doc = "Enable OCSP Stapling on servers",
    fields = ["enabled"],
)

use_ocsp_stapling = rule(
    implementation = lambda ctx: use_ocsp_stapling_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# disable-ref-track
# =========

use_disable_ref_track_provider = provider(
    doc = """Disables runtime tracking of REF state changes for pages within wiredtiger.
    Tracking the REF state changes is useful for debugging but there is a small performance cost.""",
    fields = ["enabled"],
)

use_disable_ref_track = rule(
    implementation = lambda ctx: use_disable_ref_track_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# wiredtiger
# =========

use_wiredtiger_provider = provider(
    doc = """Enable wiredtiger""",
    fields = ["enabled"],
)

use_wiredtiger = rule(
    implementation = lambda ctx: use_wiredtiger_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# glibcxx-debug
# =========

use_glibcxx_debug_provider = provider(
    doc = """Enable the glibc++ debug implementations of the C++ standard libary""",
    fields = ["enabled"],
)

use_glibcxx_debug = rule(
    implementation = lambda ctx: use_glibcxx_debug_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# otel
# =========

build_otel_provider = provider(
    doc = """Enable building otel and protobuf compiler. This has no effect on non-linux operating systems.""",
    fields = ["enabled"],
)

build_otel = rule(
    implementation = lambda ctx: build_otel_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# sanitize
# =========

sanitize_provider = provider(
    doc = "enable selected sanitizers",
    fields = ["enabled"],
)

asan = rule(
    implementation = lambda ctx: sanitize_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

fsan = rule(
    implementation = lambda ctx: sanitize_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)
lsan = rule(
    implementation = lambda ctx: sanitize_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)
msan = rule(
    implementation = lambda ctx: sanitize_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

tsan = rule(
    implementation = lambda ctx: sanitize_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

ubsan = rule(
    implementation = lambda ctx: sanitize_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# separate_debug
# =========

separate_debug_provider = provider(
    doc = "Enable splitting deubg info into a separate file (e.g. '.debug')",
    fields = ["enabled"],
)

separate_debug = rule(
    implementation = lambda ctx: separate_debug_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# dev_stacktrace
# =========

dev_stacktrace_provider = provider(
    doc = "Enable development-only pretty stacktraces",
    fields = ["enabled"],
)

dev_stacktrace = rule(
    implementation = lambda ctx: dev_stacktrace_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# enable-http-client
# =========

http_client_provider = provider(
    doc = "Enable HTTP client",
    fields = ["enabled"],
)

http_client = rule(
    implementation = lambda ctx: linkstatic_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# linkstatic
# =========

linkstatic_provider = provider(
    doc = "Configures the entire build to link statically. Disabling this on windows is not supported.",
    fields = ["enabled"],
)

linkstatic = rule(
    implementation = lambda ctx: linkstatic_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# shared_archive
# =========

shared_archive_provider = provider(
    doc = "Enable generating a shared archive file for each shared library (e.g. '.so.a')",
    fields = ["enabled"],
)

shared_archive = rule(
    implementation = lambda ctx: shared_archive_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# skip_archive
# =========

skip_archive_provider = provider(
    doc = "Skip generating archives in favor of using --start-lib --end-lib",
    fields = ["enabled"],
)

skip_archive = rule(
    implementation = lambda ctx: skip_archive_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# compress_debug_compile
# =========

compress_debug_compile_provider = provider(
    doc = "Compress the debug sections outputted by the compiler.",
    fields = ["enabled"],
)

compress_debug_compile = rule(
    implementation = lambda ctx: compress_debug_compile_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# simple_build_id
# =========

simple_build_id_provider = provider(
    doc = "Replace linker build-id with a simpler one based off output file name.",
    fields = ["enabled"],
)

simple_build_id = rule(
    implementation = lambda ctx: simple_build_id_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# build_enterprise_module
# =========

build_enterprise_provider = provider(
    doc = """Build enterprise module""",
    fields = ["enabled"],
)

build_enterprise = rule(
    implementation = lambda ctx: build_enterprise_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# streams-release-build
# =========
streams_release_build_provider = provider(
    doc = """If set, will include the enterprise streams module in a release build.""",
    fields = ["enabled"],
)

streams_release_build = rule(
    implementation = lambda ctx: streams_release_build_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# disable-streams
# =========
disable_streams_provider = provider(
    doc = """If set, will exclude the enterprise streams module in a non-release build.""",
    fields = ["enabled"],
)

disable_streams = rule(
    implementation = lambda ctx: disable_streams_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# visibility-support
# =========

visibility_support_values = ["auto", "on", "off"]

visibility_support_provider = provider(
    doc = "Enable visibility annotations",
    fields = ["type"],
)

def visibility_support_impl(ctx):
    visibility_support_value = ctx.build_setting_value
    if visibility_support_value not in visibility_support_values:
        fail(str(ctx.label) + " visibility-support allowed to take values {" + ", ".join(visibility_support_values) + "} but was set to unallowed value " + visibility_support_value)
    return visibility_support_provider(type = visibility_support_value)

visibility_support = rule(
    implementation = visibility_support_impl,
    build_setting = config.string(flag = True),
)

# =========
# dbg
# =========
dbg_provider = provider(
    doc = """Enable runtime debugging checks.""",
    fields = ["enabled"],
)

dbg = rule(
    implementation = lambda ctx: dbg_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# ==========
# dbg_level
# ==========

dbg_level_values = ["0", "1", "2", "3"]

dbg_level_provider = provider(
    doc = "Sets the level of debug information generated.",
    fields = ["level"],
)

def dbg_level_support_impl(ctx):
    dbg_level_value = ctx.build_setting_value
    if dbg_level_value not in dbg_level_values:
        fail(str(ctx.label) + "dbg_level allowed to take values {" + ", ".join(dbg_level_values) + "} but was set to unallowed value " + dbg_level_value)
    return dbg_level_provider(level = dbg_level_value)

dbg_level = rule(
    implementation = dbg_level_support_impl,
    build_setting = config.string(flag = True),
)

# =========
# debug symbols
# =========
debug_symbols_provider = provider(
    doc = """Enable the production of debug symbols.""",
    fields = ["enabled"],
)

debug_symbols = rule(
    implementation = lambda ctx: debug_symbols_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# opt
# =========
opt_values = ["auto", "on", "off", "size", "debug"]

opt_provider = provider(
    doc = "Enable compiler optimizations.",
    fields = {"opt": "choose one of " + ".".join(opt_values)},
)

def opt_impl(ctx):
    opt_value = ctx.build_setting_value
    if opt_value not in opt_values:
        fail(str(ctx.label) + " opt allowed to take values {" + ", ".join(opt_values) + "} but was set to unallowed value " + opt_value)
    return opt_provider(opt = opt_value)

opt = rule(
    implementation = opt_impl,
    build_setting = config.string(flag = True),
)

# =========
# release
# =========
release_provider = provider(
    doc = """Release build.""",
    fields = ["enabled"],
)

release = rule(
    implementation = lambda ctx: release_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# remote link
# =========
remote_link_provider = provider(
    doc = """Enable remote link features.""",
    fields = ["enabled"],
)

remote_link = rule(
    implementation = lambda ctx: remote_link_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# remote test
# =========
remote_test_provider = provider(
    doc = """Enable remote testing via remote bazel execution.""",
    fields = ["enabled"],
)

remote_test_build = rule(
    implementation = lambda ctx: remote_test_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# dwarf_version
# =========
dwarf_version_values = ["4", "5"]

dwarf_version_provider = provider(
    doc = """Sets the DWARF version (non-Windows). Incompatible with SPLIT_DWARF=1""",
    fields = {"dwarf_version": "choose one of " + ".".join(dwarf_version_values)},
)

def dwarf_version_impl(ctx):
    dwarf_version = ctx.build_setting_value
    if dwarf_version != "" and dwarf_version not in dwarf_version_values:
        fail(str(ctx.label) + " version allowed to take values {" + ", ".join(dwarf_version_values) + "} but was set to unallowed value " + dwarf_version)
    return dwarf_version_provider(dwarf_version = dwarf_version)

dwarf_version = rule(
    implementation = dwarf_version_impl,
    build_setting = config.string(flag = True),
)

# =========
# disable-warnings-as-errors
# =========

disable_warnings_as_errors_provider = provider(
    doc = """Don't add a warnings-as-errors flag to compiler command lines""",
    fields = ["enabled"],
)

disable_warnings_as_errors = rule(
    implementation = lambda ctx: disable_warnings_as_errors_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# ssl
# =========

ssl_provider = provider(doc = "Enable or Disable SSL", fields = ["enabled"])

ssl = rule(
    implementation = lambda ctx: ssl_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# thin_lto
# =========

thin_lto_provider = provider(
    doc = """Enable thin link time optimization (LTO) (experimental)""",
    fields = ["enabled"],
)

thin_lto = rule(
    implementation = lambda ctx: thin_lto_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# distributed thin lto
# =========

dtlto_provider = provider(
    doc = """Enable distributed thin link time optimization (LTO).""",
    fields = ["enabled"],
)

dtlto = rule(
    implementation = lambda ctx: dtlto_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# gcov
# =========

gcov_provider = provider(
    doc = "Choose if gcov should be used",
    fields = ["enabled"],
)

gcov = rule(
    implementation = lambda ctx: gcov_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# pgo_profile_generate
# =========

pgo_profile_generate_provider = provider(
    doc = "Choose if pgo profiling should be generated",
    fields = ["enabled"],
)

pgo_profile_generate = rule(
    implementation = lambda ctx: pgo_profile_generate_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# pgo_profile_use
# =========

pgo_profile_use_provider = provider(
    doc = "Choose if pgo profiling should be used",
    fields = ["enabled"],
)

pgo_profile_use = rule(
    implementation = lambda ctx: pgo_profile_use_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# bolt_profile_generate
# =========

bolt_profile_generate_provider = provider(
    doc = "Choose if bolt profiling should be generated",
    fields = ["enabled"],
)

bolt_profile_generate = rule(
    implementation = lambda ctx: bolt_profile_generate_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# bolt_profile_use
# =========

bolt_profile_use_provider = provider(
    doc = "Choose if bolt profiling should be used",
    fields = ["enabled"],
)

bolt_profile_use = rule(
    implementation = lambda ctx: bolt_profile_use_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# propeller_profile_generate
# =========

propeller_profile_generate_provider = provider(
    doc = "Choose if binary should be prepared to be run under perf for propeller",
    fields = ["enabled"],
)

propeller_profile_generate = rule(
    implementation = lambda ctx: propeller_profile_generate_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# propeller_profile_use
# =========

propeller_profile_use_provider = provider(
    doc = "Choose if propeller profiling should be used",
    fields = ["enabled"],
)

propeller_profile_use = rule(
    implementation = lambda ctx: propeller_profile_use_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =============
# sdkroot
# =============

sdkroot_provider = provider(
    doc = "The path to the sdk, e.g. SDKROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk",
    fields = {"path": "sdk root.]"},
)

sdkroot = rule(
    implementation = lambda ctx: sdkroot_provider(path = ctx.build_setting_value),
    build_setting = config.string(flag = True),
)

# =========
# js_engine
# =========

js_engine_provider = provider(
    doc = "JavaScript scripting engine implementation",
    fields = {"engine": "Javascript scripting engine."},
)

js_engine = rule(
    implementation = lambda ctx: js_engine_provider(engine = ctx.build_setting_value),
    build_setting = config.string(flag = True),
)

# =========
# server_js
# =========

server_js_provider = provider(
    doc = "Build mongod without JavaScript support",
    fields = ["enabled"],
)

server_js = rule(
    implementation = lambda ctx: server_js_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# create_dwp
# =========

create_dwp_provider = provider(
    doc = "Create dwp files when using install targets",
    fields = ["enabled"],
)

create_dwp = rule(
    implementation = lambda ctx: create_dwp_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# evg
# =========

evg_provider = provider(
    doc = "Enable development-only pretty stacktraces",
    fields = ["enabled"],
)

evg = rule(
    implementation = lambda ctx: evg_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)

# =========
# coverage
# =========
coverage_provider = provider(
    doc = "Set to flag that this is a coverage build (this should only be set by bazelrc)",
    fields = ["enabled"],
)

coverage = rule(
    implementation = lambda ctx: coverage_provider(enabled = ctx.build_setting_value),
    build_setting = config.bool(flag = True),
)
